const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const bootstrap = path.resolve('node_modules/bootstrap/dist/css/bootstrap.css');
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';

// webpack5内置优化已经做的很好了
module.exports = ({ development, production }) => {
  const isEnvDevelopment = development === 'development';
  const isEnvProduction = production === 'production';
  const getStyleLoaders = (cssOptions) => {
    const loaders = [
      isEnvDevelopment && require.resolve('style-loader'),
      isEnvProduction && MiniCssExtractPlugin.loader,
      {
        loader: require.resolve('css-loader'),
        options: cssOptions,
      },
      'postcss-loader',
    ].filter(Boolean);
    return loaders;
  };
  return {
    mode: isEnvProduction ? 'production' : isEnvDevelopment ? 'development' : 'development',
    devtool: isEnvProduction
      ? shouldUseSourceMap
        ? 'source-map'
        : false
      : isEnvDevelopment && 'cheap-module-source-map',
    // 编译的缓存
    cache: {
      // 也可以在内存中的
      type: 'filesystem',
    },
    entry: {
      main: './src/index.js',
    },
    // 生产环境
    // 开启tree-sharking
    // scope-hosting
    optimization: {
      minimize: isEnvProduction, // 生产环境启动压缩 文件体积更小
      minimizer: [
        new TerserPlugin({ parallel: true }), // js
        new OptimizeCSSAssetsPlugin(), // css
      ],
      // 代码块分隔
      splitChunks: {
        chunks: 'all', // all就是支持异步和同步 async sync
        minSize: 0, // 最小的大小
        minRemainingSize: 0, // 分隔出去剩下的大小
        maxSize: 0, // 最大的
        minChunks: 1, // 最小应用
        maxAsyncRequests: 30, // 异步最大请求 import()
        maxInitialRequests: 30, // 同步模块最大请求数
        // webpack5新增的
        enforceSizeThreshold: 50000, // 强制分隔的 如果一个代码太大了就会被分隔
        // 缓存组 node_modules 第三方模块
        cacheGroups: {
          defaultVendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
            reuseExistingChunk: true,
          },
          default: {
            minChunks: 2, // 一个模块被饮用了两次 会单独的提取
            priority: -20, // 优先级
            reuseExistingChunk: true, // 是否使用分隔出去的代码块
          },
        },
      },
      // 运行时代码 单独分隔 webpack要运行的代码
      runtimeChunk: {
        name: (entrypoint) => `runtime-${entrypoint.name}`,
      },
      // 持久化的缓存 named是带名字的
      // deterministic 名字的hash
      moduleIds: isEnvProduction ? 'deterministic' : 'named',
      chunkIds: isEnvProduction ? 'deterministic' : 'named',
    },
    resolve: {
      // 配置模块的查找范围 越小越好
      modules: [path.resolve('node_modules')],
      // 扩展名 越小越小
      extensions: ['.js'],
      // 别名
      alias: {
        // const bootstrap = path.resolve('node_modules/bootstrap/dist/css/bootstrap.css');
        bootstrap,
      },
      // node的核心模块不要
      fallback: {
        // node的一些核心模块 不需要
        crypto: false,
        buffer: false,
        stream: false,
      },
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                // babel的缓存 现在通过 cache来配置就可以了
                cacheDirectory: true,
                presets: ['@babel/preset-react'],
                plugins: ['@babel/plugin-proposal-class-properties'],
              },
            },
          ],
          // 配置 include和exclude
          include: path.resolve('src'),
          exclude: /node_modules/,
        },
        {
          test: /\.css$/,
          use: getStyleLoaders({ importLoaders: 1 }),
        },
      ],
    },
    devServer: {},
    plugins: [
      new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            inject: true,
            template: './public/index.html',
          },
          isEnvProduction
            ? {
                minify: {
                  // html的压缩
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
            : undefined,
        ),
      ),
      // 外部模块 通过CDN引入
      new HtmlWebpackExternalsPlugin({
        externals: [
          {
            // 外部模块 不打包这个模块 window._ 引入全局变量
            module: 'lodash',
            entry: 'https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.js',
            global: '_',
          },
        ],
      }),
    ],
  };
};
